package com.yfq.springframework.beans.annotation;

import cn.hutool.core.bean.BeanUtil;
import com.yfq.springframework.beans.BeanFactoryAware;
import com.yfq.springframework.beans.BeansException;
import com.yfq.springframework.beans.PropertyValues;
import com.yfq.springframework.beans.config.InstantiationAwareBeanPostProcessor;
import com.yfq.springframework.beans.factory.BeanFactory;
import com.yfq.springframework.beans.support.DefaultListableBeanFactory;
import com.yfq.springframework.util.ClassUtils;

import java.lang.reflect.Field;

/**
 * @author 姚凤桥
 * @date 2023/2/5 21:54
 * @description
 */
public class AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {
    private DefaultListableBeanFactory beanFactory;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        return null;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = (DefaultListableBeanFactory) beanFactory;
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        //1.解析@Value注解
        Class<?> clazz = bean.getClass();
        clazz = ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz;
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            Value value = field.getAnnotation(Value.class);
            if (value != null) {
                String finalValue = beanFactory.resolveEmbeddedValue(value.value());
                BeanUtil.setFieldValue(bean, field.getName(), finalValue);
            }
        }

        //2.解析@Autowired注解
        for (Field field : fields) {
            Autowired autowired = field.getAnnotation(Autowired.class);
            if (autowired != null) {
                Qualifier qualifier = field.getAnnotation(Qualifier.class);
                String name = qualifier != null ? qualifier.value() : field.getName();

                //从容器中找对应的bean赋值
                Object finalValue = beanFactory.getBean(name);
                if (autowired.required() && finalValue == null) {
                    throw new BeansException("没有找到bean：" + name);
                }

                BeanUtil.setFieldValue(bean, name, finalValue);
            }
        }

        return pvs;
    }
}
